home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap16 / Dibble / DibHelp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  30.8 KB  |  1,124 lines

  1. /*------------------------------------------
  2.    DIBHELP.C -- DIB Section Helper Routines 
  3.                 (c) Charles Petzold, 1998
  4.   ------------------------------------------*/
  5.  
  6. #define WINVER 0x0500
  7. #include <windows.h>
  8. #include "dibhelp.h"
  9.  
  10. #define HDIB_SIGNATURE (* (int *) "Dib ")
  11.  
  12. typedef struct
  13. {
  14.      PBYTE    * ppRow ;            // must be first field for macros!
  15.      int        iSignature ;
  16.      HBITMAP    hBitmap ;
  17.      BYTE     * pBits ;
  18.      DIBSECTION ds ;
  19.      int        iRShift[3] ;
  20.      int        iLShift[3] ;
  21. }
  22. DIBSTRUCT, * PDIBSTRUCT ;
  23.  
  24. /*---------------------------------------------------------------
  25.    DibIsValid:  Returns TRUE if hdib points to a valid DIBSTRUCT
  26.   ---------------------------------------------------------------*/
  27.  
  28. BOOL DibIsValid (HDIB hdib)
  29. {
  30.      PDIBSTRUCT pdib = hdib ;
  31.  
  32.      if (pdib == NULL)
  33.           return FALSE ;
  34.  
  35.      if (IsBadReadPtr (pdib, sizeof (DIBSTRUCT)))
  36.           return FALSE ;
  37.  
  38.      if (pdib->iSignature != HDIB_SIGNATURE)
  39.           return FALSE ;
  40.  
  41.      return TRUE ;
  42. }
  43.  
  44. /*-----------------------------------------------------------------------
  45.    DibBitmapHandle:  Returns the handle to the DIB section bitmap object
  46.   -----------------------------------------------------------------------*/
  47.  
  48. HBITMAP DibBitmapHandle (HDIB hdib)
  49. {
  50.      if (!DibIsValid (hdib))
  51.           return NULL ;
  52.      
  53.      return ((PDIBSTRUCT) hdib)->hBitmap ;
  54. }
  55.  
  56. /*-------------------------------------------
  57.    DibWidth:  Returns the bitmap pixel width
  58.   -------------------------------------------*/
  59.  
  60. int DibWidth (HDIB hdib)
  61. {
  62.      if (!DibIsValid (hdib))
  63.           return 0 ;
  64.      
  65.      return ((PDIBSTRUCT) hdib)->ds.dsBm.bmWidth ;
  66. }
  67.  
  68. /*---------------------------------------------
  69.    DibHeight:  Returns the bitmap pixel height
  70.   ---------------------------------------------*/
  71.  
  72. int DibHeight (HDIB hdib)
  73. {
  74.      if (!DibIsValid (hdib))
  75.           return 0 ; 
  76.      
  77.      return ((PDIBSTRUCT) hdib)->ds.dsBm.bmHeight ;
  78. }
  79.  
  80. /*----------------------------------------------------
  81.    DibBitCount:  Returns the number of bits per pixel
  82.   ----------------------------------------------------*/
  83.  
  84. int DibBitCount (HDIB hdib)
  85. {
  86.      if (!DibIsValid (hdib))
  87.           return 0 ;
  88.      
  89.      return ((PDIBSTRUCT) hdib)->ds.dsBm.bmBitsPixel ;
  90. }
  91.  
  92. /*--------------------------------------------------------------
  93.    DibRowLength:  Returns the number of bytes per row of pixels
  94.   --------------------------------------------------------------*/
  95.  
  96. int DibRowLength (HDIB hdib)
  97. {
  98.      if (!DibIsValid (hdib))
  99.           return 0 ;
  100.      
  101.      return 4 * ((DibWidth (hdib) * DibBitCount (hdib) + 31) / 32) ;
  102. }
  103.  
  104. /*----------------------------------------------------------------
  105.    DibNumColors:  Returns the number of colors in the color table
  106.   ----------------------------------------------------------------*/
  107.  
  108. int DibNumColors (HDIB hdib)
  109. {
  110.      PDIBSTRUCT pdib = hdib ;
  111.  
  112.      if (!DibIsValid (hdib))
  113.           return 0 ;
  114.  
  115.      if (pdib->ds.dsBmih.biClrUsed != 0)
  116.      {
  117.           return pdib->ds.dsBmih.biClrUsed ;
  118.      }
  119.      else if (DibBitCount (hdib) <= 8)
  120.      {
  121.           return 1 << DibBitCount (hdib) ;
  122.      }
  123.      return 0 ;
  124. }
  125.  
  126. /*------------------------------------------
  127.    DibMask:  Returns one of the color masks
  128.   ------------------------------------------*/
  129.  
  130. DWORD DibMask (HDIB hdib, int i)
  131. {
  132.      PDIBSTRUCT pdib = hdib ;
  133.  
  134.      if (!DibIsValid (hdib) || i < 0 || i > 2)
  135.           return 0 ;
  136.      
  137.      return pdib->ds.dsBitfields[i] ;
  138. }
  139.  
  140. /*---------------------------------------------------
  141.    DibRShift:  Returns one of the right-shift values
  142.   ---------------------------------------------------*/
  143.  
  144. int DibRShift (HDIB hdib, int i)
  145. {
  146.      PDIBSTRUCT pdib = hdib ;
  147.  
  148.      if (!DibIsValid (hdib) || i < 0 || i > 2)
  149.           return 0 ;
  150.      
  151.      return pdib->iRShift[i] ;
  152. }
  153.  
  154. /*--------------------------------------------------
  155.    DibLShift:  Returns one of the left-shift values
  156.   --------------------------------------------------*/
  157.  
  158. int DibLShift (HDIB hdib, int i)
  159. {
  160.      PDIBSTRUCT pdib = hdib ;
  161.  
  162.      if (!DibIsValid (hdib) || i < 0 || i > 2)
  163.           return 0 ;
  164.      
  165.      return pdib->iLShift[i] ;
  166. }
  167.  
  168. /*---------------------------------------------------------------
  169.    DibCompression:  Returns the value of the biCompression field
  170.   ---------------------------------------------------------------*/
  171.  
  172. int DibCompression (HDIB hdib)
  173. {
  174.      if (!DibIsValid (hdib))
  175.           return 0 ;
  176.  
  177.      return ((PDIBSTRUCT) hdib)->ds.dsBmih.biCompression ;
  178. }
  179.  
  180. /*--------------------------------------------------------------
  181.    DibIsAddressable:  Returns TRUE if the DIB is not compressed
  182.   --------------------------------------------------------------*/
  183.  
  184. BOOL DibIsAddressable (HDIB hdib)
  185. {
  186.      int iCompression ;
  187.  
  188.      if (!DibIsValid (hdib))
  189.           return FALSE ;
  190.  
  191.      iCompression = DibCompression (hdib) ;
  192.  
  193.      if (iCompression == BI_RGB || iCompression == BI_BITFIELDS)
  194.          return TRUE ;
  195.  
  196.      return FALSE ;
  197. }
  198.  
  199. /*---------------------------------------------------------------------------
  200.    These functions return the sizes of various components of the DIB section
  201.      AS THEY WOULD APPEAR in a packed DIB. These functions aid in converting
  202.      the DIB section to a packed DIB and in saving DIB files.
  203.   ---------------------------------------------------------------------------*/
  204.  
  205. DWORD DibInfoHeaderSize (HDIB hdib)
  206. {
  207.      if (!DibIsValid (hdib))
  208.           return 0 ;
  209.  
  210.      return ((PDIBSTRUCT) hdib)->ds.dsBmih.biSize ;
  211. }
  212.  
  213. DWORD DibMaskSize (HDIB hdib)
  214. {
  215.      PDIBSTRUCT pdib = hdib ;
  216.  
  217.      if (!DibIsValid (hdib))
  218.           return 0 ;
  219.  
  220.      if (pdib->ds.dsBmih.biCompression == BI_BITFIELDS)
  221.           return 3 * sizeof (DWORD) ;
  222.  
  223.      return 0 ;
  224. }
  225.  
  226. DWORD DibColorSize (HDIB hdib)
  227. {
  228.      return DibNumColors (hdib) * sizeof (RGBQUAD) ;
  229.  
  230. DWORD DibInfoSize (HDIB hdib)
  231. {
  232.      return DibInfoHeaderSize(hdib) + DibMaskSize(hdib) + DibColorSize(hdib) ;
  233. }
  234.  
  235. DWORD DibBitsSize (HDIB hdib)
  236. {
  237.      PDIBSTRUCT pdib = hdib ;
  238.  
  239.      if (!DibIsValid (hdib))
  240.           return 0 ;
  241.  
  242.      if (pdib->ds.dsBmih.biSizeImage != 0)
  243.      {
  244.           return pdib->ds.dsBmih.biSizeImage ;
  245.      }
  246.      return DibHeight (hdib) * DibRowLength (hdib) ;
  247. }
  248.  
  249. DWORD DibTotalSize (HDIB hdib)
  250. {
  251.      return DibInfoSize (hdib) + DibBitsSize (hdib) ;
  252. }
  253.  
  254. /*----------------------------------------------------------------------
  255.    These functions return pointers to the various components of the DIB 
  256.      section.
  257.   ----------------------------------------------------------------------*/
  258.  
  259. BITMAPINFOHEADER * DibInfoHeaderPtr (HDIB hdib)
  260. {
  261.      if (!DibIsValid (hdib))
  262.           return NULL ;
  263.      
  264.      return & (((PDIBSTRUCT) hdib)->ds.dsBmih) ;
  265. }
  266.  
  267. DWORD * DibMaskPtr (HDIB hdib)
  268. {
  269.      PDIBSTRUCT pdib = hdib ;
  270.  
  271.      if (!DibIsValid (hdib))
  272.           return 0 ;
  273.  
  274.      return pdib->ds.dsBitfields ;
  275. }
  276.  
  277. void * DibBitsPtr (HDIB hdib)
  278. {
  279.      if (!DibIsValid (hdib))
  280.           return NULL ;
  281.      
  282.      return ((PDIBSTRUCT) hdib)->pBits ;
  283. }
  284.  
  285. /*------------------------------------------------------
  286.    DibSetColor:  Obtains entry from the DIB color table
  287.   ------------------------------------------------------*/
  288.  
  289. BOOL DibGetColor (HDIB hdib, int index, RGBQUAD * prgb)
  290. {
  291.      PDIBSTRUCT pdib = hdib ;
  292.      HDC        hdcMem ;
  293.      int        iReturn ;
  294.  
  295.      if (!DibIsValid (hdib))
  296.           return 0 ;
  297.  
  298.      hdcMem = CreateCompatibleDC (NULL) ;
  299.      SelectObject (hdcMem, pdib->hBitmap) ;
  300.      iReturn = GetDIBColorTable (hdcMem, index, 1, prgb) ;
  301.      DeleteDC (hdcMem) ;
  302.  
  303.      return iReturn ? TRUE : FALSE ;
  304. }
  305.  
  306. /*----------------------------------------------------
  307.    DibGetColor:  Sets an entry in the DIB color table
  308.   ----------------------------------------------------*/
  309.  
  310. BOOL DibSetColor (HDIB hdib, int index, RGBQUAD * prgb)
  311. {
  312.      PDIBSTRUCT pdib = hdib ;
  313.      HDC        hdcMem ;
  314.      int        iReturn ;
  315.  
  316.      if (!DibIsValid (hdib))
  317.           return 0 ;
  318.  
  319.      hdcMem = CreateCompatibleDC (NULL) ;
  320.      SelectObject (hdcMem, pdib->hBitmap) ;
  321.      iReturn = SetDIBColorTable (hdcMem, index, 1, prgb) ;
  322.      DeleteDC (hdcMem) ;
  323.  
  324.      return iReturn ? TRUE : FALSE ;
  325. }
  326.  
  327. /*-----------------------------------------------------------------
  328.    DibPixelPtr:  Returns a pointer to the pixel at position (x, y)
  329.   -----------------------------------------------------------------*/
  330.  
  331. BYTE * DibPixelPtr (HDIB hdib, int x, int y)
  332. {
  333.      if (!DibIsAddressable (hdib))
  334.           return NULL ;
  335.  
  336.      if (x < 0 || x >= DibWidth (hdib) || y < 0 || y >= DibHeight (hdib))
  337.           return NULL ;
  338.  
  339.      return (((PDIBSTRUCT) hdib)->ppRow)[y] + (x * DibBitCount (hdib) >> 3) ;
  340. }
  341.  
  342. /*-----------------------------------------------
  343.    DibGetPixel:  Obtains a pixel value at (x, y)
  344.   -----------------------------------------------*/
  345.  
  346. DWORD DibGetPixel (HDIB hdib, int x, int y)
  347. {
  348.      PBYTE pPixel ;
  349.  
  350.      if (!(pPixel = DibPixelPtr (hdib, x, y)))
  351.           return 0 ;
  352.  
  353.      switch (DibBitCount (hdib))
  354.      {
  355.      case  1:  return 0x01 & (* pPixel >> (7 - (x & 7))) ;
  356.      case  4:  return 0x0F & (* pPixel >> (x & 1 ? 0 : 4)) ;
  357.      case  8:  return * pPixel ;
  358.      case 16:  return * (WORD *) pPixel ;
  359.      case 24:  return 0x00FFFFFF & * (DWORD *) pPixel ; 
  360.      case 32:  return * (DWORD *) pPixel ;
  361.      }
  362.      return 0 ;
  363. }
  364.  
  365. /*--------------------------------------------
  366.    DibSetPixel:  Sets a pixel value at (x, y)
  367.   --------------------------------------------*/
  368.  
  369. BOOL DibSetPixel (HDIB hdib, int x, int y, DWORD dwPixel)
  370. {
  371.      PBYTE pPixel ;
  372.  
  373.      if (!(pPixel = DibPixelPtr (hdib, x, y)))
  374.           return FALSE ;
  375.  
  376.      switch (DibBitCount (hdib))
  377.      {
  378.      case  1:  * pPixel &= ~(1     << (7 - (x & 7))) ;
  379.                * pPixel |= dwPixel << (7 - (x & 7)) ;
  380.                break ;
  381.  
  382.      case  4:  * pPixel &= 0x0F    << (x & 1 ? 4 : 0) ;
  383.                * pPixel |= dwPixel << (x & 1 ? 0 : 4) ;
  384.                break ;
  385.  
  386.      case  8:  * pPixel = (BYTE) dwPixel ;
  387.                break ;
  388.  
  389.      case 16:  * (WORD *) pPixel = (WORD) dwPixel ;
  390.                break ;
  391.  
  392.      case 24:  * (RGBTRIPLE *) pPixel = * (RGBTRIPLE *) &dwPixel ; 
  393.                break ;
  394.  
  395.      case 32:  * (DWORD *) pPixel = dwPixel ;
  396.                break ;
  397.      default:
  398.           return FALSE ;
  399.      }
  400.      return TRUE ;
  401. }
  402.  
  403. /*------------------------------------------------------
  404.    DibGetPixelColor:  Obtains the pixel color at (x, y)
  405.   ------------------------------------------------------*/
  406.  
  407. BOOL DibGetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb)
  408. {
  409.      DWORD      dwPixel ;
  410.      int        iBitCount ;
  411.      PDIBSTRUCT pdib = hdib ;
  412.  
  413.           // Get bit count; also use this as a validity check
  414.  
  415.      if (0 == (iBitCount = DibBitCount (hdib)))
  416.           return FALSE ;
  417.  
  418.           // Get the pixel value
  419.  
  420.      dwPixel = DibGetPixel (hdib, x, y) ;
  421.  
  422.           // If the bit-count is 8 or less, index the color table
  423.  
  424.      if (iBitCount <= 8)
  425.           return DibGetColor (hdib, (int) dwPixel, prgb) ;
  426.  
  427.           // If the bit-count is 24, just use the pixel
  428.  
  429.      else if (iBitCount == 24)
  430.      {
  431.           * (RGBTRIPLE *) prgb = * (RGBTRIPLE *) & dwPixel ;
  432.           prgb->rgbReserved = 0 ;
  433.      }
  434.  
  435.           // If the bit-count is 32 and the biCompression field is BI_RGB,
  436.           //   just use the pixel
  437.  
  438.      else if (iBitCount == 32 && 
  439.                pdib->ds.dsBmih.biCompression == BI_RGB)
  440.      {
  441.           * prgb = * (RGBQUAD *) & dwPixel ;
  442.      }
  443.  
  444.           // Otherwise, use the mask and shift values
  445.           //   (for best performance, don't use DibMask and DibShift functions)
  446.      else
  447.      {
  448.           prgb->rgbRed   = (BYTE) (((pdib->ds.dsBitfields[0] & dwPixel) 
  449.                                    >> pdib->iRShift[0]) << pdib->iLShift[0]) ;
  450.  
  451.           prgb->rgbGreen = (BYTE) (((pdib->ds.dsBitfields[1] & dwPixel) 
  452.                                    >> pdib->iRShift[1]) << pdib->iLShift[1]) ;
  453.  
  454.           prgb->rgbBlue  = (BYTE) (((pdib->ds.dsBitfields[2] & dwPixel) 
  455.                                    >> pdib->iRShift[2]) << pdib->iLShift[2]) ;
  456.      }
  457.      return TRUE ;
  458. }
  459.  
  460. /*---------------------------------------------------
  461.    DibSetPixelColor:  Sets the pixel color at (x, y) 
  462.   ---------------------------------------------------*/
  463.  
  464. BOOL DibSetPixelColor (HDIB hdib, int x, int y, RGBQUAD * prgb)
  465. {
  466.      DWORD      dwPixel ;
  467.      int        iBitCount ;
  468.      PDIBSTRUCT pdib = hdib ;
  469.  
  470.           // Don't do this function for DIBs with color tables
  471.  
  472.      iBitCount = DibBitCount (hdib) ;
  473.  
  474.      if (iBitCount <= 8)
  475.           return FALSE ;
  476.  
  477.           // The rest is just the opposite of DibGetPixelColor
  478.  
  479.      else if (iBitCount == 24)
  480.      {
  481.           * (RGBTRIPLE *) & dwPixel = * (RGBTRIPLE *) prgb ;
  482.           dwPixel &= 0x00FFFFFF ;
  483.      }
  484.  
  485.      else if (iBitCount == 32 &&
  486.                pdib->ds.dsBmih.biCompression == BI_RGB)
  487.      {
  488.           * (RGBQUAD *) & dwPixel = * prgb ;
  489.      }
  490.  
  491.      else
  492.      {
  493.           dwPixel  = (((DWORD) prgb->rgbRed >> pdib->iLShift[0]) 
  494.                          << pdib->iRShift[0]) ; 
  495.  
  496.           dwPixel |= (((DWORD) prgb->rgbGreen >> pdib->iLShift[1])
  497.                          << pdib->iRShift[1]) ; 
  498.  
  499.           dwPixel |= (((DWORD) prgb->rgbBlue >> pdib->iLShift[2])
  500.                          << pdib->iRShift[2]) ; 
  501.      }
  502.  
  503.      DibSetPixel (hdib, x, y, dwPixel) ;
  504.      return TRUE ;
  505. }
  506.  
  507. /*--------------------------------------------------------------
  508.    Calculating shift values from color masks is required by the 
  509.      DibCreateFromInfo function.
  510.   --------------------------------------------------------------*/
  511.  
  512. static int MaskToRShift (DWORD dwMask)
  513. {
  514.      int iShift ;
  515.  
  516.      if (dwMask == 0)
  517.           return 0 ;
  518.  
  519.      for (iShift = 0 ; !(dwMask & 1) ; iShift++)
  520.           dwMask >>= 1 ;
  521.  
  522.      return iShift ;
  523. }
  524.  
  525. static int MaskToLShift (DWORD dwMask)
  526. {
  527.      int iShift ;
  528.  
  529.      if (dwMask == 0)
  530.           return 0 ;
  531.  
  532.      while (!(dwMask & 1))
  533.           dwMask >>= 1 ;
  534.  
  535.      for (iShift = 0 ; dwMask & 1 ; iShift++)
  536.           dwMask >>= 1 ;
  537.  
  538.      return 8 - iShift ;
  539. }
  540.  
  541. /*-------------------------------------------------------------------------
  542.    DibCreateFromInfo: All DIB creation functions ultimately call this one.
  543.      This function is responsible for calling CreateDIBSection, allocating
  544.      memory for DIBSTRUCT, and setting up the row pointer.
  545.   -------------------------------------------------------------------------*/
  546.  
  547. HDIB DibCreateFromInfo (BITMAPINFO * pbmi)
  548. {
  549.      BYTE      * pBits ;
  550.      DIBSTRUCT * pdib ;
  551.      HBITMAP     hBitmap ;
  552.      int         i, iRowLength, cy, y ;
  553.      
  554.      hBitmap = CreateDIBSection (NULL, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0) ;
  555.  
  556.      if (hBitmap == NULL)
  557.           return NULL ;
  558.  
  559.      if (NULL == (pdib = malloc (sizeof (DIBSTRUCT))))
  560.      {
  561.           DeleteObject (hBitmap) ;
  562.           return NULL ;
  563.      }
  564.  
  565.      pdib->iSignature = HDIB_SIGNATURE ;
  566.      pdib->hBitmap    = hBitmap ;
  567.      pdib->pBits      = pBits ;
  568.  
  569.      GetObject (hBitmap, sizeof (DIBSECTION), &pdib->ds) ;
  570.  
  571.           // Notice that we can now use the DIB information functions 
  572.           //   defined above.
  573.  
  574.           // If the compression is BI_BITFIELDS, calculate shifts from masks
  575.  
  576.      if (DibCompression (pdib) == BI_BITFIELDS)
  577.      {
  578.           for (i = 0 ; i < 3 ; i++)
  579.           {
  580.                pdib->iLShift[i] = MaskToLShift (pdib->ds.dsBitfields[i]) ;
  581.                pdib->iRShift[i] = MaskToRShift (pdib->ds.dsBitfields[i]) ;
  582.           }
  583.      }
  584.  
  585.           // If the compression is BI_RGB, but bit-count is 16 or 32,
  586.           //   set the bitfields and the masks
  587.  
  588.      else if (DibCompression (pdib) == BI_RGB)
  589.      {
  590.           if (DibBitCount (pdib) == 16)
  591.           {
  592.                pdib->ds.dsBitfields[0] = 0x00007C00 ;
  593.                pdib->ds.dsBitfields[1] = 0x000003E0 ;
  594.                pdib->ds.dsBitfields[2] = 0x0000001F ;
  595.  
  596.                pdib->iRShift[0] = 10 ;
  597.                pdib->iRShift[1] =  5 ;
  598.                pdib->iRShift[2] =  0 ; 
  599.  
  600.                pdib->iLShift[0] =  3 ;
  601.                pdib->iLShift[1] =  3 ;
  602.                pdib->iLShift[2] =  3 ;
  603.           }
  604.           else if (DibBitCount (pdib) == 24 || DibBitCount (pdib) == 32)
  605.           {
  606.                pdib->ds.dsBitfields[0] = 0x00FF0000 ;
  607.                pdib->ds.dsBitfields[1] = 0x0000FF00 ;
  608.                pdib->ds.dsBitfields[2] = 0x000000FF ;
  609.  
  610.                pdib->iRShift[0] = 16 ;
  611.                pdib->iRShift[1] =  8 ;
  612.                pdib->iRShift[2] =  0 ; 
  613.  
  614.                pdib->iLShift[0] =  0 ;
  615.                pdib->iLShift[1] =  0 ;
  616.                pdib->iLShift[2] =  0 ;
  617.           }
  618.      }
  619.           // Allocate an array of pointers to each row in the DIB
  620.  
  621.      cy = DibHeight (pdib) ;
  622.  
  623.      if (NULL == (pdib->ppRow = malloc (cy * sizeof (BYTE *))))
  624.      {
  625.           free (pdib) ;
  626.           DeleteObject (hBitmap) ;
  627.           return NULL ;
  628.      }
  629.  
  630.           // Initialize them.
  631.  
  632.      iRowLength = DibRowLength (pdib) ; 
  633.  
  634.      if (pbmi->bmiHeader.biHeight > 0)       // ie, bottom up
  635.      {
  636.           for (y = 0 ; y < cy ; y++)
  637.                pdib->ppRow[y] = pBits + (cy - y - 1) * iRowLength ;
  638.      }
  639.      else                                    // top down
  640.      {
  641.           for (y = 0 ; y < cy ; y++)
  642.                pdib->ppRow[y] = pBits + y * iRowLength ;
  643.      }
  644.      return pdib ;
  645. }
  646.  
  647. /*--------------------------------------------------
  648.    DibDelete:  Frees all memory for the DIB section
  649.   --------------------------------------------------*/
  650.  
  651. BOOL DibDelete (HDIB hdib)
  652. {
  653.      DIBSTRUCT * pdib = hdib ;
  654.  
  655.      if (!DibIsValid (hdib))
  656.           return FALSE ;
  657.  
  658.      free (pdib->ppRow) ;
  659.      DeleteObject (pdib->hBitmap) ;
  660.      free (pdib) ;
  661.      return TRUE ;
  662. }
  663.  
  664. /*----------------------------------------------------
  665.    DibCreate: Creates an HDIB from explicit arguments
  666.   ----------------------------------------------------*/ 
  667.  
  668. HDIB DibCreate (int cx, int cy, int cBits, int cColors)
  669. {
  670.      BITMAPINFO * pbmi ;
  671.      DWORD        dwInfoSize ;
  672.      HDIB         hDib ;
  673.      int          cEntries ;
  674.  
  675.      if (cx <= 0 || cy <= 0 || 
  676.          ((cBits !=  1) && (cBits !=  4) && (cBits !=  8) && 
  677.           (cBits != 16) && (cBits != 24) && (cBits != 32)))
  678.      {
  679.           return NULL ;
  680.      }
  681.  
  682.      if (cColors != 0)
  683.           cEntries = cColors ;
  684.      else if (cBits <= 8)
  685.           cEntries = 1 << cBits ;
  686.  
  687.      dwInfoSize = sizeof (BITMAPINFOHEADER) + (cEntries - 1) * sizeof (RGBQUAD);
  688.  
  689.      if (NULL == (pbmi = malloc (dwInfoSize)))
  690.      {
  691.           return NULL ;
  692.      }
  693.  
  694.      ZeroMemory (pbmi, dwInfoSize) ;
  695.  
  696.      pbmi->bmiHeader.biSize          = sizeof (BITMAPINFOHEADER) ;
  697.      pbmi->bmiHeader.biWidth         = cx ;
  698.      pbmi->bmiHeader.biHeight        = cy ;
  699.      pbmi->bmiHeader.biPlanes        = 1 ;
  700.      pbmi->bmiHeader.biBitCount      = cBits ;
  701.      pbmi->bmiHeader.biCompression   = BI_RGB ;
  702.      pbmi->bmiHeader.biSizeImage     = 0 ;
  703.      pbmi->bmiHeader.biXPelsPerMeter = 0 ;
  704.      pbmi->bmiHeader.biYPelsPerMeter = 0 ;
  705.      pbmi->bmiHeader.biClrUsed       = cColors ;
  706.      pbmi->bmiHeader.biClrImportant  = 0 ;
  707.  
  708.      hDib = DibCreateFromInfo (pbmi) ;
  709.      free (pbmi) ;
  710.  
  711.      return hDib ;
  712. }
  713.  
  714. /*--------------------------------------------------
  715.    DibCopyToInfo:  Builds BITMAPINFO structure.
  716.                    Used by DibCopy and DibCopyToDdb
  717.   --------------------------------------------------*/
  718.  
  719. static BITMAPINFO * DibCopyToInfo (HDIB hdib)
  720. {
  721.      BITMAPINFO * pbmi ;
  722.      int          i, iNumColors ;
  723.      RGBQUAD    * prgb ;
  724.  
  725.      if (!DibIsValid (hdib))
  726.           return NULL ;
  727.  
  728.           // Allocate the memory
  729.  
  730.      if (NULL == (pbmi = malloc (DibInfoSize (hdib))))
  731.           return NULL ;
  732.  
  733.           // Copy the information header
  734.  
  735.      CopyMemory (pbmi, DibInfoHeaderPtr (hdib), 
  736.                                         sizeof (BITMAPINFOHEADER));
  737.           
  738.           // Copy the possible color masks
  739.  
  740.      prgb = (RGBQUAD *) ((BYTE *) pbmi + sizeof (BITMAPINFOHEADER)) ;
  741.  
  742.      if (DibMaskSize (hdib))
  743.      {
  744.           CopyMemory (prgb, DibMaskPtr (hdib), 3 * sizeof (DWORD)) ;
  745.  
  746.           prgb = (RGBQUAD *) ((BYTE *) prgb + 3 * sizeof (DWORD)) ;
  747.      }
  748.           // Copy the color table
  749.  
  750.      iNumColors = DibNumColors (hdib) ;
  751.  
  752.      for (i = 0 ; i < iNumColors ; i++)
  753.           DibGetColor (hdib, i, prgb + i) ;
  754.  
  755.      return pbmi ;
  756. }
  757.  
  758. /*-------------------------------------------------------------------
  759.    DibCopy:  Creates a new DIB section from an existing DIB section,
  760.      possibly swapping the DIB width and height.
  761.   -------------------------------------------------------------------*/
  762.  
  763. HDIB DibCopy (HDIB hdibSrc, BOOL fRotate)
  764. {
  765.      BITMAPINFO * pbmi ;
  766.      BYTE       * pBitsSrc, * pBitsDst ;
  767.      HDIB         hdibDst ;
  768.  
  769.      if (!DibIsValid (hdibSrc))
  770.           return NULL ;
  771.  
  772.      if (NULL == (pbmi = DibCopyToInfo (hdibSrc)))
  773.           return NULL ;
  774.  
  775.      if (fRotate)
  776.      {
  777.           pbmi->bmiHeader.biWidth = DibHeight (hdibSrc) ;
  778.           pbmi->bmiHeader.biHeight = DibWidth (hdibSrc) ;
  779.      }
  780.  
  781.      hdibDst = DibCreateFromInfo (pbmi) ;
  782.      free (pbmi) ;
  783.  
  784.      if (hdibDst == NULL)
  785.           return NULL ;
  786.  
  787.           // Copy the bits
  788.  
  789.      if (!fRotate)
  790.      {
  791.           pBitsSrc = DibBitsPtr (hdibSrc) ;
  792.           pBitsDst = DibBitsPtr (hdibDst) ;
  793.  
  794.           CopyMemory (pBitsDst, pBitsSrc, DibBitsSize (hdibSrc)) ;
  795.      }
  796.      return hdibDst ;
  797. }
  798.  
  799. /*----------------------------------------------------------------------
  800.    DibCopyToPackedDib is generally used for saving DIBs and for 
  801.      transferring DIBs to the clipboard. In the second case, the second 
  802.      argument should be set to TRUE so that the memory is allocated 
  803.      with the GMEM_SHARE flag.
  804.   ----------------------------------------------------------------------*/
  805.  
  806. BITMAPINFO * DibCopyToPackedDib (HDIB hdib, BOOL fUseGlobal)
  807. {
  808.      BITMAPINFO * pPackedDib ;
  809.      BYTE       * pBits ;
  810.      DWORD        dwDibSize ;
  811.      HDC          hdcMem ;
  812.      HGLOBAL      hGlobal ;
  813.      int          iNumColors ;
  814.      PDIBSTRUCT   pdib = hdib ;
  815.      RGBQUAD    * prgb ;
  816.  
  817.      if (!DibIsValid (hdib))
  818.           return NULL ;
  819.  
  820.           // Allocate memory for packed DIB
  821.  
  822.      dwDibSize = DibTotalSize (hdib) ;
  823.  
  824.      if (fUseGlobal)
  825.      {
  826.           hGlobal = GlobalAlloc (GHND | GMEM_SHARE, dwDibSize) ;
  827.           pPackedDib = GlobalLock (hGlobal) ;
  828.      }
  829.      else
  830.      {
  831.           pPackedDib = malloc (dwDibSize) ;
  832.      }
  833.  
  834.      if (pPackedDib == NULL) 
  835.           return NULL ;
  836.  
  837.           // Copy the information header
  838.  
  839.      CopyMemory (pPackedDib, &pdib->ds.dsBmih, sizeof (BITMAPINFOHEADER)) ;
  840.  
  841.      prgb = (RGBQUAD *) ((BYTE *) pPackedDib + sizeof (BITMAPINFOHEADER)) ;
  842.  
  843.           // Copy the possible color masks
  844.  
  845.      if (pdib->ds.dsBmih.biCompression == BI_BITFIELDS)
  846.      {
  847.           CopyMemory (prgb, pdib->ds.dsBitfields, 3 * sizeof (DWORD)) ;
  848.  
  849.           prgb = (RGBQUAD *) ((BYTE *) prgb + 3 * sizeof (DWORD)) ;
  850.      }
  851.           // Copy the color table
  852.  
  853.      if (iNumColors = DibNumColors (hdib))
  854.      {
  855.           hdcMem = CreateCompatibleDC (NULL) ;
  856.           SelectObject (hdcMem, pdib->hBitmap) ;
  857.           GetDIBColorTable (hdcMem, 0, iNumColors, prgb) ;
  858.           DeleteDC (hdcMem) ;
  859.      }
  860.  
  861.      pBits = (BYTE *) (prgb + iNumColors) ;
  862.  
  863.           // Copy the bits
  864.  
  865.      CopyMemory (pBits, pdib->pBits, DibBitsSize (pdib)) ;
  866.  
  867.           // If last argument is TRUE, unlock global memory block and 
  868.           //   cast it to pointer in preparation for return
  869.  
  870.      if (fUseGlobal)
  871.      {
  872.           GlobalUnlock (hGlobal) ;
  873.           pPackedDib = (BITMAPINFO *) hGlobal ;     
  874.      }
  875.      return pPackedDib ;
  876. }
  877.  
  878. /*------------------------------------------------------------------
  879.    DibCopyFromPackedDib is generally used for pasting DIBs from the 
  880.      clipboard.
  881.   ------------------------------------------------------------------*/
  882.  
  883. HDIB DibCopyFromPackedDib (BITMAPINFO * pPackedDib)
  884. {
  885.      BYTE     * pBits ;     
  886.      DWORD      dwInfoSize, dwMaskSize, dwColorSize ;
  887.      int        iBitCount ;
  888.      PDIBSTRUCT pdib ;
  889.  
  890.           // Get the size of the information header and do validity check
  891.      
  892.      dwInfoSize = pPackedDib->bmiHeader.biSize ;
  893.  
  894.      if (dwInfoSize != sizeof (BITMAPCOREHEADER) &&
  895.          dwInfoSize != sizeof (BITMAPINFOHEADER) &&
  896.          dwInfoSize != sizeof (BITMAPV4HEADER) &&
  897.          dwInfoSize != sizeof (BITMAPV5HEADER))
  898.      {
  899.           return NULL ;
  900.      }
  901.           // Get the possible size of the color masks
  902.  
  903.      if (dwInfoSize == sizeof (BITMAPINFOHEADER) &&
  904.           pPackedDib->bmiHeader.biCompression == BI_BITFIELDS)
  905.      {
  906.           dwMaskSize = 3 * sizeof (DWORD) ;
  907.      }
  908.      else
  909.      {
  910.           dwMaskSize = 0 ;
  911.      }
  912.           // Get the size of the color table
  913.  
  914.      if (dwInfoSize == sizeof (BITMAPCOREHEADER))
  915.      {
  916.           iBitCount = ((BITMAPCOREHEADER *) pPackedDib)->bcBitCount ;
  917.  
  918.           if (iBitCount <= 8)
  919.           {
  920.                dwColorSize = (1 << iBitCount) * sizeof (RGBTRIPLE) ;
  921.           }
  922.           else
  923.                dwColorSize = 0 ;
  924.      }
  925.      else           // all non-OS/2 compatible DIBs
  926.      {
  927.           if (pPackedDib->bmiHeader.biClrUsed > 0)
  928.           {
  929.                dwColorSize = pPackedDib->bmiHeader.biClrUsed * sizeof (RGBQUAD);
  930.           }
  931.           else if (pPackedDib->bmiHeader.biBitCount <= 8)
  932.           {
  933.                dwColorSize = (1 << pPackedDib->bmiHeader.biBitCount) * 
  934.                                                        sizeof (RGBQUAD) ;
  935.           }
  936.           else
  937.           {
  938.                dwColorSize = 0 ;
  939.           }
  940.      }
  941.           // Finally, get the pointer to the bits in the packed-DIB
  942.  
  943.      pBits = (BYTE *) pPackedDib + dwInfoSize + dwMaskSize + dwColorSize ;
  944.  
  945.           // Create the HDIB from the packed DIB pointer
  946.  
  947.      pdib = DibCreateFromInfo (pPackedDib) ;
  948.  
  949.           // Copy the pixel bits
  950.  
  951.      CopyMemory (pdib->pBits, pBits, DibBitsSize (pdib)) ;
  952.  
  953.      return pdib ;
  954. }
  955.  
  956. /*-----------------------------------------------------
  957.    DibFileLoad:  Creates a DIB section from a DIB file
  958.   -----------------------------------------------------*/
  959.  
  960. HDIB DibFileLoad (const TCHAR * szFileName)
  961. {
  962.      BITMAPFILEHEADER bmfh ;
  963.      BITMAPINFO     * pbmi ;
  964.      BOOL             bSuccess ;
  965.      DWORD            dwInfoSize, dwBitsSize, dwBytesRead ;
  966.      HANDLE           hFile ;
  967.      HDIB             hDib ;
  968.  
  969.           // Open the file: read access, prohibit write access
  970.  
  971.      hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
  972.                          OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) ;
  973.  
  974.      if (hFile == INVALID_HANDLE_VALUE)
  975.           return NULL ;
  976.  
  977.           // Read in the BITMAPFILEHEADER
  978.  
  979.      bSuccess = ReadFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER), 
  980.                           &dwBytesRead, NULL) ;
  981.  
  982.      if (!bSuccess || (dwBytesRead != sizeof (BITMAPFILEHEADER))         
  983.                    || (bmfh.bfType != * (WORD *) "BM"))
  984.      {
  985.           CloseHandle (hFile) ;
  986.           return NULL ;
  987.      }
  988.           // Allocate memory for the information structure & read it in
  989.  
  990.      dwInfoSize = bmfh.bfOffBits - sizeof (BITMAPFILEHEADER) ;
  991.  
  992.      if (NULL == (pbmi = malloc (dwInfoSize)))
  993.      {
  994.           CloseHandle (hFile) ;
  995.           return NULL ;
  996.      }
  997.  
  998.      bSuccess = ReadFile (hFile, pbmi, dwInfoSize, &dwBytesRead, NULL) ;
  999.  
  1000.      if (!bSuccess || (dwBytesRead != dwInfoSize))
  1001.      {
  1002.           CloseHandle (hFile) ;
  1003.           free (pbmi) ;
  1004.           return NULL ;
  1005.      }
  1006.           // Create the DIB
  1007.  
  1008.      hDib = DibCreateFromInfo (pbmi) ;
  1009.      free (pbmi) ;
  1010.  
  1011.      if (hDib == NULL)
  1012.      {
  1013.           CloseHandle (hFile) ;
  1014.           return NULL ;
  1015.      }
  1016.           // Read in the bits
  1017.  
  1018.      dwBitsSize = bmfh.bfSize - bmfh.bfOffBits ;
  1019.  
  1020.      bSuccess = ReadFile (hFile, ((PDIBSTRUCT) hDib)->pBits, 
  1021.                           dwBitsSize, &dwBytesRead, NULL) ;
  1022.      CloseHandle (hFile) ;
  1023.  
  1024.      if (!bSuccess || (dwBytesRead != dwBitsSize))
  1025.      {
  1026.           DibDelete (hDib) ;
  1027.           return NULL ;
  1028.      }
  1029.      return hDib ;
  1030. }
  1031.  
  1032. /*---------------------------------------------
  1033.    DibFileSave:  Saves a DIB section to a file
  1034.   ---------------------------------------------*/
  1035.  
  1036. BOOL DibFileSave (HDIB hdib, const TCHAR * szFileName)
  1037. {
  1038.      BITMAPFILEHEADER bmfh ;
  1039.      BITMAPINFO     * pbmi ;
  1040.      BOOL             bSuccess ;
  1041.      DWORD            dwTotalSize, dwBytesWritten ;
  1042.      HANDLE           hFile ;
  1043.  
  1044.      hFile = CreateFile (szFileName, GENERIC_WRITE, 0, NULL,
  1045.                          CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;
  1046.  
  1047.      if (hFile == INVALID_HANDLE_VALUE)
  1048.           return FALSE ;
  1049.  
  1050.      dwTotalSize  = DibTotalSize (hdib) ;
  1051.  
  1052.      bmfh.bfType      = * (WORD *) "BM" ;
  1053.      bmfh.bfSize      = sizeof (BITMAPFILEHEADER) + dwTotalSize ;
  1054.      bmfh.bfReserved1 = 0 ;
  1055.      bmfh.bfReserved2 = 0 ;
  1056.      bmfh.bfOffBits   = bmfh.bfSize - DibBitsSize (hdib) ;
  1057.  
  1058.           // Write the BITMAPFILEHEADER
  1059.  
  1060.      bSuccess = WriteFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER), 
  1061.                            &dwBytesWritten, NULL) ;
  1062.  
  1063.      if (!bSuccess || (dwBytesWritten != sizeof (BITMAPFILEHEADER)))
  1064.      {
  1065.           CloseHandle (hFile) ;
  1066.           DeleteFile (szFileName) ;
  1067.           return FALSE ;
  1068.      }
  1069.           // Get entire DIB in packed DIB format
  1070.  
  1071.      if (NULL == (pbmi = DibCopyToPackedDib (hdib, FALSE)))
  1072.      {
  1073.           CloseHandle (hFile) ;
  1074.           DeleteFile (szFileName) ;
  1075.           return FALSE ;
  1076.      }
  1077.           // Write out the packed-DIB
  1078.  
  1079.      bSuccess = WriteFile (hFile, pbmi, dwTotalSize, &dwBytesWritten, NULL) ;
  1080.      CloseHandle (hFile) ;
  1081.      free (pbmi) ;
  1082.  
  1083.      if (!bSuccess || (dwBytesWritten != dwTotalSize))
  1084.      {
  1085.           DeleteFile (szFileName) ;
  1086.           return FALSE ;
  1087.      }
  1088.      return TRUE ;
  1089. }
  1090.  
  1091. /*---------------------------------------------------
  1092.    DibCopyToDdb:  For more efficient screen displays
  1093.   ---------------------------------------------------*/
  1094.  
  1095. HBITMAP DibCopyToDdb (HDIB hdib, HWND hwnd, HPALETTE hPalette)
  1096. {
  1097.      BITMAPINFO * pbmi ;
  1098.      HBITMAP      hBitmap ;
  1099.      HDC          hdc ;
  1100.  
  1101.      if (!DibIsValid (hdib))
  1102.           return NULL ;
  1103.  
  1104.      if (NULL == (pbmi = DibCopyToInfo (hdib)))
  1105.           return NULL ;
  1106.  
  1107.      hdc = GetDC (hwnd) ;
  1108.  
  1109.      if (hPalette)
  1110.      {
  1111.           SelectPalette (hdc, hPalette, FALSE) ;
  1112.           RealizePalette (hdc) ;
  1113.      }
  1114.      
  1115.      hBitmap = CreateDIBitmap (hdc, DibInfoHeaderPtr (hdib), CBM_INIT,
  1116.                                DibBitsPtr (hdib), pbmi, DIB_RGB_COLORS) ;
  1117.  
  1118.      ReleaseDC (hwnd, hdc) ;
  1119.      free (pbmi) ;
  1120.  
  1121.      return hBitmap ;
  1122. }
  1123.